package com.bsj.sipgateway.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsj.power.common.def.entity.Scene;
import com.bsj.power.common.def.entity.gb28181.Device;
import com.bsj.power.common.def.vo.SceneDeviceVO;
import com.bsj.power.common.mapper.DeviceMapper;
import com.bsj.power.common.mapper.SceneMapper;
import com.bsj.sipgateway.web.service.IDeviceService;
import com.bsj.sipgateway.web.service.ISceneService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.ArrayStack;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import redis.clients.bsj.JedisClusterBSJ;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author zhaoyang
 * @Date 2024/5/11 14:42
 */
@Slf4j
@Service("sceneServiceImpl")
public class SceneServiceImpl implements ISceneService {

    @Autowired
    private SceneMapper sceneMapper;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    @Qualifier("deviceServiceImpl")
    private IDeviceService videoDeviceService;

    @Autowired
    private JedisClusterBSJ jedisClusterBSJ;

    @Value("${sip.cvrSceneId}")
    private Integer cvrSceneId;


    @Override
    public Scene add(Scene scene) {
        // 不填上级id，默认是最上级场景
        if (scene.getPid() == null) {
            scene.setPid(-1);
        }
        scene.setCreateTime(new Date());
        int count = sceneMapper.insert(scene);
        if (count > 0) {
//            RedisSceneInfo redisSceneInfo = new RedisSceneInfo();
//            BeanUtils.copyProperties(scene, redisSceneInfo);
//            jedisClusterBSJ.set(RedisConstant.REDIS_SCENE_INFO + scene.getSceneName(), JSON.toJSONString(redisSceneInfo));
            return scene;
        }
        return null;

    }


    @Override
    public boolean existsByName(String sceneName) {
        QueryWrapper<Scene> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("scene_name", sceneName);
        return sceneMapper.exists(queryWrapper);
    }

    @Override
    public boolean update(Scene scene) {
//        QueryWrapper<Scene> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("scene_name", scene.getSceneName());
//        Scene oldScene = sceneMapper.selectOne(queryWrapper);
//        if (oldScene != null) {
//            if (!oldScene.getId().equals(scene.getId())) {
//                // 说明新修改的名称已经存在了
//                throw new ApiException(JsonResultEnum.NAME_IS_EXIST);
//            }
//        }

//        Scene scene1 = sceneMapper.selectById(scene.getId());
//        jedisClusterBSJ.del(RedisConstant.REDIS_SCENE_INFO + scene1.getSceneName());

        int count = sceneMapper.updateById(scene);
        // 重新写入redis中的scene
//        RedisSceneInfo redisSceneInfo = new RedisSceneInfo();
//        BeanUtils.copyProperties(scene, redisSceneInfo);
//        jedisClusterBSJ.set(RedisConstant.REDIS_SCENE_INFO + scene.getSceneName(), JSON.toJSONString(redisSceneInfo));
        return count > 0;
    }

    @Override
    public Scene findById(Integer sceneId) {
        return sceneMapper.selectById(sceneId);
    }

    @Override
    public void updateSceneIdByIds(Integer sceneId, Long[] dids) {
        deviceMapper.updateSceneIdByIds(sceneId, dids);
    }

    @Override
    public void unbindVideoDevice(Integer sceneId, Long did) {
        deviceMapper.updateDeviceSceneIdNullByDid(did);

    }

    @Override
    public void deleteScene(Integer sceneId) {
//        deviceMapper.updateDeviceSceneIdNullBySceneId(sceneId);
//        Scene scene = sceneMapper.selectById(sceneId);
//        jedisClusterBSJ.del(RedisConstant.REDIS_SCENE_INFO + scene.getSceneName());

        sceneMapper.deleteById(sceneId);
    }

    @Override
    public List<Device> listVideoDevicesBySceneId(Integer sceneId) {
        List<Integer> sceneIds = new ArrayList<>();
        // 要把下级场景也添加进去，当前场景是只有一级的，查询一次即可
        sceneIds.add(sceneId);
        List<Integer> childIds = sceneMapper.selectSceneIdByPid(sceneId);
        if (!CollectionUtils.isEmpty(childIds)) {
            sceneIds.addAll(childIds);
        }
        List<Device> devices = videoDeviceService.selectBySceneIds(sceneIds);
        return devices;
    }

    @Override
    public IPage<Scene> pageQuerySceneList(Integer page, Integer size, Integer isSensitived) {
        Page<Scene> iPage = new Page<>(page, size);
        QueryWrapper<Scene> wrapper = null;
        if (isSensitived != null) {
            wrapper = new QueryWrapper<>();
            wrapper.eq("sensitived", 1); // 查询敏感场景
            if (cvrSceneId != null) {
                wrapper.notIn("id", List.of(cvrSceneId));
            }
        }
        return sceneMapper.selectPage(iPage, wrapper);

    }

    @Override
    public List<Scene> findSubSceneList(Integer sceneId) {
        QueryWrapper<Scene> sceneQueryWrapper = null;
        if (cvrSceneId != null) { // 不查cvr所在的分组，也不查询cvr设备
            sceneQueryWrapper = new QueryWrapper<>();
            sceneQueryWrapper.notIn("id", List.of(cvrSceneId));
        }
        List<Scene> scenes = sceneMapper.selectList(sceneQueryWrapper);
        int pid = -1;
        if (sceneId != null) { // 如果sceneId==null，就查山东下的所有
            Scene scene = sceneMapper.selectById(sceneId);
            pid = scene.getId();
        }
        return getSubSceneList(pid, scenes);

    }


    /**
     * 根据父id和所有场景遍历出该父id的所有下级场景，不包含父id
     *
     * @param parentId
     * @param allScenes
     * @return
     */
    private static List<Scene> getSubSceneList(int parentId, List<Scene> allScenes) {
        List<Scene> subScenes = new ArrayList<>();
        for (Scene scene : allScenes) {
            if (scene.getPid() == parentId) {
                subScenes.add(scene);
                List<Scene> lowerSubScenes = getSubSceneList(scene.getId(), allScenes);
                subScenes.addAll(lowerSubScenes);
            }
        }
        return subScenes;
    }

    @Override
    public List<Scene> findAllScene() {
        return sceneMapper.selectList(null);
    }

    @Override
    public List<Scene> vagueSearchForSceneName(String sceneName) {
        QueryWrapper<Scene> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("scene_name", sceneName);
        List<Scene> scenes = sceneMapper.selectList(queryWrapper);
        return scenes;
    }

    @Override
    public List<Scene> selectScenesByIds(List<Integer> sceneIds) {
        List<Scene> scenes = sceneMapper.selectBatchIds(sceneIds);
        return scenes;
    }

    @Override
    public IPage<Device> listDeviceBySceneIdAndCondition(Integer sceneId, String condition, Integer pageNumber, Integer pageSize) {
        /**
         * 不能两个参数都不填
         * 如果不选sceneId，选了condition，根据condition查全部
         * 如果选了sceneId，没选condition，根据sceneId查
         * 如果选了sceneId，也选了condition，就根据两个查
         */
        IPage<Device> iPage = new Page<>(pageNumber, pageSize);
        QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
        // 如果不选sceneId，选了condition，根据condition查全部
        if (!StringUtils.isEmpty(condition)) {
            queryWrapper.like("nick_name", condition).or().like("device_id", condition);
        }
        if (sceneId != null) {
            // 如果选了场景id，并且场景是最上级场景，就要查该场景下的所有设备
            Scene scene = sceneMapper.selectById(sceneId);
            List<Scene> allScenes = sceneMapper.selectList(null);
            List<Scene> subSceneList = getSubSceneList(scene.getId(), allScenes);
            subSceneList.add(scene); // 把自己也加进去，否则出现查本级场景查不出设备的问题
            if (CollectionUtils.isEmpty(subSceneList)) {
                return iPage;
            }
            List<Integer> sceneIds = subSceneList.stream().mapToInt(Scene::getId).boxed().collect(Collectors.toList());
            queryWrapper.in("scene_id", sceneIds);
        }
        return deviceMapper.selectPage(iPage, queryWrapper);
    }

    @Override
    public List<Scene> findByIds(List<Integer> sceneIds) {
        return sceneMapper.selectBatchIds(sceneIds);
    }

    @Override
    public List<Scene> findSensitiveScene() {
        QueryWrapper<Scene> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sensitived", 1);
        return sceneMapper.selectList(queryWrapper);
    }

    @Override
    public Scene findBySceneName(String sceneName) {
        QueryWrapper<Scene> sceneQueryWrapper = new QueryWrapper<>();
        sceneQueryWrapper.eq("scene_name", sceneName);
        return sceneMapper.selectOne(sceneQueryWrapper);
    }

    /**
     * 获取当前场景的所有下级或上级场景id（包括本身）
     *
     * @param sceneId
     * @param type    1:上级 2:下级
     * @return java.util.List<java.lang.Integer>
     * @author ljx
     * @time 2024/9/5 16:01
     */
    @Override
    public List<Integer> getSceneIds(Integer sceneId, Integer type) {
        Set<Integer> set = new HashSet<>();
        //需要查询的下级id
        Set<Integer> sceneIds = new HashSet<>() {
            {
                add(sceneId);
                set.add(sceneId);
            }
        };
        if (type == 1) {
            getSuUId(set, sceneIds);
        } else {
            getLoUId(set, sceneIds);
        }
        return set.stream().collect(Collectors.toList());
    }

    /**
     * 获取下级场景id
     *
     * @param set
     * @param sceneIds
     * @return void
     * @author ljx
     * @time 2024/9/5 16:01
     */
    private void getLoUId(Set<Integer> set, Set<Integer> sceneIds) {
        QueryWrapper<Scene> queryWrapper = new QueryWrapper();
        queryWrapper.in("pid", sceneIds);
        queryWrapper.select("id");
        List<Scene> sceneList = sceneMapper.selectList(queryWrapper);
        if (!CollectionUtils.isEmpty(sceneList)) {
            sceneIds.clear();
            for (Scene scene : sceneList) {
                Integer id = scene.getId();
                set.add(id);
                sceneIds.add(id);
            }
            getLoUId(set, sceneIds);
        }
    }

    /**
     * 获取上级场景id
     *
     * @param set
     * @param sceneIds
     * @return void
     * @author ljx
     * @time 2024/9/5 16:01
     */
    private void getSuUId(Set<Integer> set, Set<Integer> sceneIds) {
        QueryWrapper<Scene> queryWrapper = new QueryWrapper();
        queryWrapper.in("id", sceneIds);
        queryWrapper.select("pid");
        List<Scene> sceneList = sceneMapper.selectList(queryWrapper);
        List<Integer> sceneIdList = sceneList.stream().map(Scene::getPid).collect(Collectors.toList());
        sceneIdList.remove(new Integer(-1));
        if (!CollectionUtils.isEmpty(sceneIdList)) {
            sceneIds.clear();
            for (Integer sceneId : sceneIdList) {
                set.add(sceneId);
                sceneIds.add(sceneId);
            }
            getSuUId(set, sceneIds);
        }
    }

    @Override
    public List<Integer> selectSceneIdByPid(Integer sceneId) {
        return sceneMapper.selectSceneIdByPid(sceneId);
    }

    @Override
    public List<Scene> selectSceneSByBuilding(int i) {
        return sceneMapper.selectSceneSByBuilding(i);
    }



}
